package com.tools.common.object.json.deserializer;

import com.fasterxml.jackson.core.JacksonException;
import com.fasterxml.jackson.core.JsonParser;
import com.fasterxml.jackson.core.JsonToken;
import com.fasterxml.jackson.databind.DeserializationContext;
import com.fasterxml.jackson.databind.deser.std.StdDeserializer;
import com.tools.common.container.JsonPair;
import com.tools.common.container.MapEnum;
import com.tools.common.container.OwnMap;
import com.tools.common.container.OwnPair;
import com.tools.common.container.r.OnlyReadHashMap;
import com.tools.common.container.r.OnlyReadLinkedMap;
import com.tools.common.container.r.OnlyReadTreeMap;
import com.tools.common.object.Note;
import com.tools.common.object.json.DeserializerHandler;
import com.tools.common.object.json.JsonKit;

import java.io.IOException;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.Properties;
import java.util.TreeMap;
import java.util.concurrent.ConcurrentSkipListMap;

/**
 * 键值对容器类型的反序列化处理器
 * */
@Note("键值对容器类型的反序列化处理器")
public class KVTypeHandler {

    private KVTypeHandler() {}

    @Note("处理、转换获取 OwnMap 自定义键值对容器实例")
    public static StdDeserializer<OwnMap> ownMapDeserializer() {
        return new StdDeserializer<OwnMap>(OwnMap.class) {
            @Override
            public OwnMap deserialize(JsonParser jsonParser, DeserializationContext deserializationContext) throws IOException, JacksonException {
                JsonToken jsonToken = jsonParser.currentToken();
                if(jsonToken == null) {
                    jsonToken = jsonParser.nextToken();
                }
                if(jsonToken == JsonToken.START_OBJECT) {
                    OwnMap<String, Object> ownMap = new OwnMap<>(MapEnum.LINKED);
                    JsonKit.pairsParseToken(jsonParser, ownMap);
                    return ownMap;
                }
                throw new ClassCastException("无法将数组类型的 JSON 字符串转为 com.tools.common.container.OwnMap 实例");
            }
        };
    }


    @Note("处理、转换获取 OwnPair 自定义键值对容器实例")
    public static StdDeserializer<OwnPair> ownPairDeserializer() {
        return new StdDeserializer<OwnPair>(OwnPair.class) {
            @Override
            public OwnPair deserialize(JsonParser jsonParser, DeserializationContext deserializationContext) throws IOException, JacksonException {
                JsonToken jsonToken = jsonParser.currentToken();
                if(jsonToken == null) {
                    jsonToken = jsonParser.nextToken();
                }
                if(jsonToken == JsonToken.START_OBJECT) {
                    OwnPair ownPair = new OwnPair(MapEnum.LINKED);
                    JsonKit.pairsParseToken(jsonParser, ownPair);
                    return ownPair;
                }
                throw new ClassCastException("无法将数组类型的 JSON 字符串转为 com.tools.common.container.OwnPair 实例");
            }
        };
    }


    @Note("处理、转换获取 JsonPair 自定义键值对容器实例")
    public static StdDeserializer<JsonPair> jsonPairDeserializer() {
        return new StdDeserializer<JsonPair>(JsonPair.class) {
            @Override
            public JsonPair deserialize(JsonParser jsonParser, DeserializationContext deserializationContext) throws IOException, JacksonException {
                JsonToken jsonToken = jsonParser.currentToken();
                if(jsonToken == null) {
                    jsonToken = jsonParser.nextToken();
                }
                if(jsonToken == JsonToken.START_OBJECT) {
                    JsonPair jsonPair = new JsonPair();
                    JsonKit.pairsParseToken(jsonParser, jsonPair);
                    return jsonPair;
                }
                throw new ClassCastException("无法将数组类型的 JSON 字符串转为 com.tools.common.container.JsonPair 实例");
            }
        };
    }


    @Note("处理、转换获取 TreeMap 集合实例")
    public static StdDeserializer<TreeMap> treeMapDeserializer() {
        return new StdDeserializer<TreeMap>(TreeMap.class) {
            @Override
            public TreeMap deserialize(JsonParser jsonParser, DeserializationContext deserializationContext) throws IOException {
                JsonToken jsonToken = jsonParser.currentToken();
                if(jsonToken == null) {
                    jsonToken = jsonParser.nextToken();
                }
                if(jsonToken == JsonToken.START_OBJECT) {
                    TreeMap map = new TreeMap<>();
                    try {
                        JsonKit.mapParseToken(jsonParser, map);
                        return map;
                    } catch (ClassCastException e) {
                        TreeMap treeMap = new TreeMap<>(DeserializerHandler.getDefaultComparator());
                        treeMap.putAll(map);
                        JsonKit.mapParseToken(jsonParser, treeMap);
                        return treeMap;
                    }
                }
                throw new ClassCastException("无法将数组类型的 JSON 字符串转为 java.util.TreeMap 实例");
            }
        };
    }


    @Note("处理、转换获取 ConcurrentSkipListMap 集合实例")
    public static StdDeserializer<ConcurrentSkipListMap> concurrentSkipListMapDeserializer() {
        return new StdDeserializer<ConcurrentSkipListMap>(ConcurrentSkipListMap.class) {
            @Override
            public ConcurrentSkipListMap deserialize(JsonParser jsonParser, DeserializationContext deserializationContext) throws IOException {
                JsonToken jsonToken = jsonParser.currentToken();
                if(jsonToken == null) {
                    jsonToken = jsonParser.nextToken();
                }
                if(jsonToken == JsonToken.START_OBJECT) {
                    ConcurrentSkipListMap map = new ConcurrentSkipListMap<>();
                    try {
                        JsonKit.mapParseToken(jsonParser, map);
                        return map;
                    } catch (ClassCastException e) {
                        ConcurrentSkipListMap treeMap = new ConcurrentSkipListMap<>(DeserializerHandler.getDefaultComparator());
                        treeMap.putAll(map);
                        JsonKit.mapParseToken(jsonParser, treeMap);
                        return treeMap;
                    }
                }
                throw new ClassCastException("无法将数组类型的 JSON 字符串转为 java.util.concurrent.ConcurrentSkipListMap 实例");
            }
        };
    }


    @Note("处理、转换获取 OnlyReadHashMap 只读 HashMap 实例")
    public static StdDeserializer<OnlyReadHashMap> onlyReadHashMapDeserializer() {
        return new StdDeserializer<OnlyReadHashMap>(OnlyReadHashMap.class) {
            @Override
            public OnlyReadHashMap deserialize(JsonParser jsonParser, DeserializationContext deserializationContext) throws IOException, JacksonException {
                JsonToken jsonToken = jsonParser.currentToken();
                if(jsonToken == null) {
                    jsonToken = jsonParser.nextToken();
                }
                if(jsonToken == JsonToken.START_OBJECT) {
                    HashMap map = new HashMap<>();
                    JsonKit.mapParseToken(jsonParser, map);
                    return new OnlyReadHashMap<>(map);
                }
                throw new ClassCastException("无法将数组类型的 JSON 字符串转为 com.tools.common.container.r.OnlyReadHashMap 实例");
            }
        };
    }


    @Note("处理、转换获取 OnlyReadLinkedMap 只读 LinkedHashMap 实例")
    public static StdDeserializer<OnlyReadLinkedMap> onlyReadLinkedMapDeserializer() {
        return new StdDeserializer<OnlyReadLinkedMap>(OnlyReadLinkedMap.class) {
            @Override
            public OnlyReadLinkedMap deserialize(JsonParser jsonParser, DeserializationContext deserializationContext) throws IOException, JacksonException {
                JsonToken jsonToken = jsonParser.currentToken();
                if(jsonToken == null) {
                    jsonToken = jsonParser.nextToken();
                }
                if(jsonToken == JsonToken.START_OBJECT) {
                    LinkedHashMap map = new LinkedHashMap<>();
                    JsonKit.mapParseToken(jsonParser, map);
                    return new OnlyReadLinkedMap<>(map);
                }
                throw new ClassCastException("无法将数组类型的 JSON 字符串转为 com.tools.common.container.r.OnlyReadTreeMap 实例");
            }
        };
    }


    @Note("处理、转换获取 OnlyReadTreeMap 只读 TreeMap 实例")
    public static StdDeserializer<OnlyReadTreeMap> onlyReadTreeMapDeserializer() {
        return new StdDeserializer<OnlyReadTreeMap>(OnlyReadLinkedMap.class) {
            @Override
            public OnlyReadTreeMap deserialize(JsonParser jsonParser, DeserializationContext deserializationContext) throws IOException, JacksonException {
                JsonToken jsonToken = jsonParser.currentToken();
                if(jsonToken == null) {
                    jsonToken = jsonParser.nextToken();
                }
                if(jsonToken == JsonToken.START_OBJECT) {
                    TreeMap map = new TreeMap<>();
                    try {
                        JsonKit.mapParseToken(jsonParser, map);
                        return new OnlyReadTreeMap<>(map);
                    } catch (ClassCastException e) {
                        JsonKit.mapParseToken(jsonParser, map);
                        return new OnlyReadTreeMap<>(map, DeserializerHandler.getDefaultComparator());
                    }
                }
                throw new ClassCastException("无法将数组类型的 JSON 字符串转为 com.tools.common.container.r.OnlyReadTreeMap 实例");
            }
        };
    }

    @Note("处理、转换获取 Properties 实例")
    public static StdDeserializer<Properties> propertiesDeserializer() {
        return new StdDeserializer<Properties>(Properties.class) {
            @Override
            public Properties deserialize(JsonParser jsonParser, DeserializationContext deserializationContext) throws IOException, JacksonException {
                JsonToken jsonToken = jsonParser.currentToken();
                if(jsonToken == null) {
                    jsonToken = jsonParser.nextToken();
                }
                if(jsonToken == JsonToken.START_OBJECT) {
                    Properties properties = new Properties();
                    JsonKit.mapParseToken(jsonParser, properties);
                    return properties;
                }
                throw new ClassCastException("无法将数组类型的 JSON 字符串转为 java.util.Properties 实例");
            }
        };
    }
}
